//------------------------------------------------------------
//  Filename: fiber_move_proc.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2016-12-02 15:08
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module FIBER_MOVE_PROC ( 
    input  wire        clk_100mhz,  
    input  wire        resetn,  

    input  wire [7:0]  touch_status,
    output wire [31:0] fiber_push_status,
    input  wire [31:0] fiber_aux_ctrl,
    input  wire [31:0] fusion_push_ctrl,
    output reg  [31:0] fusion_push_state,
    output reg  [31:0] fusion_proc_state,
	output reg         fusion_proc_intr,
	
    input  wire [11:0] fusion_fast_l_x,
    input  wire [11:0] fusion_slow_l_x,
    input  wire [11:0] fusion_fast_r_x,
    input  wire [11:0] fusion_slow_r_x,
    input  wire [31:0] fusion_force_cfg,
    input  wire [31:0] fusion_time_cfg,
    
    input  wire [31:0] p0_move_porc_data,
    input  wire        p0_move_porc_last,  
    input  wire        p0_move_porc_v,  

    input  wire [31:0] p1_move_porc_data,
    input  wire        p1_move_porc_last,  
    input  wire        p1_move_porc_v,  

    output reg  [31:0] gaoya_ctrl_time,
    output reg  [7:0]  gaoya_ctrl_force,
    input  wire        force_pause_l,
    input  wire        force_pause_r,
    output reg  [31:0] motor_move_l,
    output reg  [31:0] motor_move_r
);  
//--------------------------------------------------------
wire clk = clk_100mhz;
wire rst = ~resetn;
//--------------------------------------------------------
localparam TENTION_DELAY_TIME = 15*10000000; //1.5s
localparam VIDEO_DELAY_TIME   = 5*10000000; //0.5s
//--------------------------------------------------------
wire direct_front = 1'b1;
wire stop_true    = 1'b1;
wire stop_false   = 1'b0;
wire pause_true   = 1'b1;
wire pause_false  = 1'b0;
//--------------------------------------------------------
reg  fast_l_edge_found;
reg  slow_l_edge_found;
reg  fast_r_edge_found;
reg  slow_r_edge_found;
reg  push_en;
reg  views_sel;
reg  auto_splice;
reg  tention_mod;
reg  fusion_touch;
reg  hall_touch;
reg  posr_touch;
reg  posl_touch;
reg  init_touch;
reg  fiber_l_base_err;
reg  fiber_r_base_err;
reg  fiber_l_missed_err;
reg  fiber_r_missed_err;
reg  fiber_l_fast_obj_found;
reg  fiber_l_slow_obj_found;
reg  fiber_l_creep_obj_found;
reg  fiber_l_base_ready;
reg  key_continue;
reg  fiber_align_ok;
reg  fiber_no_err;
reg  fusion_start;
reg  fusion_init;
reg  caliberation;
reg  pausemode1;
reg  pausemode2;
reg  engineer_mode;
reg  key_init;
reg  tention_rdy;
reg  fiber_clean_ok;
reg  fiber_r_base_ready;
reg  shell_flag;
reg  shell_open;
reg  shell_close;
reg  keep_idle;
reg  splice_act;
reg  posr_ready;
reg  posl_ready;
reg  push_video_rdy;
reg  fusion_touch_ff1;
reg  init_touch_ff1;
reg  posr_touch_ff1;
reg  posl_touch_ff1;
reg  fiber_r_fast_obj_found;
reg  fiber_r_slow_obj_found;
reg  fiber_r_creep_obj_found;
reg  fiber_push_reset;
reg  pre_splice_ok;
reg  splice_proc_ok;
reg  splice_area_bad;
//--------------------------------------------------------
reg  fast_l_edge_touch;
reg  fast_m_edge_touch;
reg  fast_n_edge_touch;
reg  slow_l_edge_touch;
reg  slow_m_edge_touch;
reg  slow_n_edge_touch;
reg  fast_r_edge_touch;
reg  fast_s_edge_touch;
reg  fast_t_edge_touch;
reg  slow_r_edge_touch;
reg  slow_s_edge_touch;
reg  slow_t_edge_touch;
reg  creep_l_edge_touch;
reg  creep_r_edge_touch;
//-------------------------------------------------------------
wire [31:0] move_porc_data = p0_move_porc_data;//(views_sel)?(p1_move_porc_data):(p0_move_porc_data);
wire        move_porc_last = p0_move_porc_last;//(views_sel)?(p1_move_porc_last):(p0_move_porc_last);  
wire        move_porc_v    = p0_move_porc_v   ;//(views_sel)?(p1_move_porc_v   ):(p0_move_porc_v   );  
//-------------------------------------------------------------
wire [11:0] fusion_fast_l_b = fusion_fast_l_x     ;
wire [11:0] fusion_fast_m_b = fusion_fast_l_x - 16;
wire [11:0] fusion_fast_n_b = fusion_fast_l_x - 8 ;
wire [11:0] fusion_fast_r_b = fusion_fast_r_x     ;
wire [11:0] fusion_fast_s_b = fusion_fast_r_x + 16;
wire [11:0] fusion_fast_t_b = fusion_fast_r_x + 8 ;
//-------------------------------------------------------------
wire [11:0] fusion_slow_l_b = fusion_slow_l_x - 32;
wire [11:0] fusion_slow_m_b = fusion_slow_l_x - 48;
wire [11:0] fusion_slow_n_b = fusion_slow_l_x - 64;
wire [11:0] fusion_slow_r_b = fusion_slow_r_x + 32;
wire [11:0] fusion_slow_s_b = fusion_slow_r_x + 48;
wire [11:0] fusion_slow_t_b = fusion_slow_r_x + 64;
//-------------------------------------------------------------
wire [11:0] fusion_creep_l_b= fusion_slow_l_x     ;
wire [11:0] fusion_creep_r_b= fusion_slow_r_x     ;
//-------------------------------------------------------------
reg[7:0] last_push;
reg[5:0] last_speed;
reg[5:0] slow_speed;
//--------------------------------------------------------
localparam SPLICE_READY      = 'h0_0001;
localparam SPLICE_RESET      = 'h0_0002;
localparam SPLICE_IDLE       = 'h0_0004;
localparam SPLICE_NOACT      = 'h0_0008;
localparam SPLICE_START      = 'h0_0010;
localparam SPLICE_DASH       = 'h0_0020;
localparam SPLICE_CLEAN      = 'h0_0040;
localparam SPLICE_ADJUST     = 'h0_0080;
localparam SPLICE_CLOSE      = 'h0_0100;
localparam SPLICE_PAUSE1     = 'h0_0200;
localparam SPLICE_ALIGN      = 'h0_0400;
localparam SPLICE_PAUSE2     = 'h0_0800;
localparam SPLICE_PREACT     = 'h0_1000; 
localparam SPLICE_PROC       = 'h0_2000; 
localparam SPLICE_REPORT     = 'h0_4000;
localparam SPLICE_TENTION    = 'h0_8000;
localparam SPLICE_ERR        = 'h1_0000;
localparam SPLICE_INIT       = 'h2_0000;
localparam SPLICE_AREA_ERR   = 'h4_0000;
//--------------------------------------------------------
reg[31:0]  cur_splice_state;
reg[31:0]  nxt_splice_state;
//-------------------------------------------------------------
localparam PUSH_L_INIT  = 'h0001; 
localparam PUSH_L_BASE  = 'h0002; 
localparam PUSH_L_IDLE  = 'h0004; 
localparam PUSH_L_READY = 'h0008; 
localparam PUSH_L_FAST  = 'h0010; 
localparam PUSH_L_WAIT  = 'h0020; 
localparam PUSH_L_SLOW  = 'h0040; 
localparam PUSH_L_CREEP = 'h0080; 
localparam PUSH_L_OK    = 'h0100; 
localparam PUSH_L_ERR   = 'h0200; 
//-------------------------------------------------------------
reg[15:0] cur_push_l_state;
reg[15:0] nxt_push_l_state;
//-------------------------------------------------------------
localparam PUSH_R_INIT  = 'h0001;
localparam PUSH_R_BASE  = 'h0002;
localparam PUSH_R_IDLE  = 'h0004;
localparam PUSH_R_READY = 'h0008;
localparam PUSH_R_FAST  = 'h0010;
localparam PUSH_R_WAIT  = 'h0020;
localparam PUSH_R_SLOW  = 'h0040;
localparam PUSH_R_CREEP = 'h0080;
localparam PUSH_R_OK    = 'h0100;
localparam PUSH_R_ERR   = 'h0200;
//-------------------------------------------------------------
reg[15:0] cur_push_r_state;
reg[15:0] nxt_push_r_state;
//-------------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        cur_push_l_state <= PUSH_L_INIT;    
    end 
    else begin 
        cur_push_l_state <= nxt_push_l_state;    
    end 
end 
//--------------------------------------------------------
always @(*) begin
    if((cur_splice_state == SPLICE_RESET)||(cur_splice_state == SPLICE_INIT)) begin
        if(cur_push_l_state == PUSH_L_BASE) begin
            nxt_push_l_state = cur_push_l_state; //open shell discharge
        end
        else begin
            nxt_push_l_state = PUSH_L_INIT; //open shell discharge
        end
    end
    else begin
        case ( cur_push_l_state )
            PUSH_L_INIT  : begin
                if(posl_ready) begin
                    nxt_push_l_state = PUSH_L_BASE;
                end 
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end
            end
            PUSH_L_BASE  : begin
                if(fiber_l_base_ready) begin 
                    nxt_push_l_state = PUSH_L_IDLE;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end
            end
            PUSH_L_IDLE : begin
                if(cur_splice_state == SPLICE_DASH) begin
                    nxt_push_l_state = PUSH_L_READY;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end
            end 
            PUSH_L_READY  : begin
                if(push_video_rdy) begin
                    nxt_push_l_state = PUSH_L_FAST;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end
            end
            PUSH_L_FAST   : begin
                if(fiber_l_base_err|fiber_l_missed_err)begin
                    nxt_push_l_state = PUSH_L_ERR;
                end
                else if(fiber_l_fast_obj_found) begin 
                    nxt_push_l_state = PUSH_L_WAIT;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end            
            end
            PUSH_L_WAIT      : begin
                if(cur_splice_state == SPLICE_CLOSE) begin
                    nxt_push_l_state = PUSH_L_SLOW;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end
            end
            PUSH_L_SLOW : begin
                if(~fiber_l_fast_obj_found) begin
                    nxt_push_l_state = PUSH_L_FAST;
                end
                else if(fiber_l_slow_obj_found) begin 
                    nxt_push_l_state = PUSH_L_CREEP;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end             
            end
            PUSH_L_CREEP : begin
                if(~fiber_l_fast_obj_found) begin
                    nxt_push_l_state = PUSH_L_FAST;
                end
                else if(fiber_l_creep_obj_found) begin 
                    nxt_push_l_state = PUSH_L_OK;
                end
                else begin
                    nxt_push_l_state = cur_push_l_state;
                end        
            end
            PUSH_L_OK          : begin
                nxt_push_l_state = cur_push_l_state;
            end   
            PUSH_L_ERR        : begin
                nxt_push_l_state = cur_push_l_state;
            end            
            default: begin
                nxt_push_l_state = PUSH_L_IDLE;
            end        
        endcase
    end
end 
//-------------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        cur_push_r_state <= PUSH_R_INIT;    
    end 
    else begin 
        cur_push_r_state <= nxt_push_r_state;    
    end 
end 
//--------------------------------------------------------
always @(*) begin 
    if((cur_splice_state == SPLICE_RESET)||(cur_splice_state == SPLICE_INIT)) begin
        if(cur_push_r_state == PUSH_R_BASE) begin
            nxt_push_r_state = cur_push_r_state; //open shell discharge
        end
        else begin
            nxt_push_r_state = PUSH_R_INIT; //open shell discharge
        end
    end
    else begin
        case ( cur_push_r_state )
            PUSH_R_INIT  : begin
                if(posr_ready) begin
                    nxt_push_r_state = PUSH_R_BASE;
                end 
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end
            end                
            PUSH_R_BASE  : begin
                if(fiber_r_base_ready) begin 
                    nxt_push_r_state = PUSH_R_IDLE;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end
            end
            PUSH_R_IDLE : begin
                if(cur_splice_state == SPLICE_DASH) begin
                    nxt_push_r_state = PUSH_R_READY;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end
            end   
            PUSH_R_READY  : begin
                if(push_video_rdy) begin
                    nxt_push_r_state = PUSH_R_FAST;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end
            end                 
            PUSH_R_FAST : begin
                if(fiber_r_base_err|fiber_r_missed_err)begin
                    nxt_push_r_state = PUSH_R_ERR;
                end
                else if(fiber_r_fast_obj_found) begin 
                    nxt_push_r_state = PUSH_R_WAIT;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end            
            end
            PUSH_R_WAIT : begin
                if(cur_splice_state == SPLICE_CLOSE) begin
                    nxt_push_r_state = PUSH_R_SLOW;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end
            end
            PUSH_R_SLOW : begin // clean at the same time
                if(~fiber_r_fast_obj_found) begin
                    nxt_push_r_state = PUSH_R_FAST;
                end                
                else if(fiber_r_slow_obj_found) begin 
                    nxt_push_r_state = PUSH_R_CREEP;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end             
            end
            PUSH_R_CREEP : begin
                if(~fiber_r_fast_obj_found) begin
                    nxt_push_r_state = PUSH_R_FAST;
                end                
                else if(fiber_r_creep_obj_found) begin 
                    nxt_push_r_state = PUSH_R_OK;
                end
                else begin
                    nxt_push_r_state = cur_push_r_state;
                end   
            end   
            PUSH_R_OK : begin
                nxt_push_r_state = cur_push_r_state ;
            end  
            PUSH_R_ERR : begin
                nxt_push_r_state = cur_push_r_state ;
            end 
        endcase
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        cur_splice_state <= SPLICE_RESET;
    end 
    else begin 
        cur_splice_state <= nxt_splice_state;
    end 
end 
//--------------------------------------------------------
always @(*) begin
    if(shell_open||key_init||fusion_init) begin
        nxt_splice_state = SPLICE_RESET; //open shell discharge
    end
    else begin
        case (cur_splice_state)
            SPLICE_READY  : begin
                if((cur_push_l_state == PUSH_L_IDLE)&&
                   (cur_push_r_state == PUSH_R_IDLE)) begin 
                    nxt_splice_state = SPLICE_IDLE;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end 
            end
            SPLICE_RESET  : begin
                nxt_splice_state = SPLICE_READY;
            end
            SPLICE_IDLE   : begin
                if(keep_idle) begin // 
                    nxt_splice_state = SPLICE_NOACT;
                end
                else if(splice_act) begin
                    nxt_splice_state = SPLICE_START;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end 
            end    
            SPLICE_NOACT : begin
                nxt_splice_state = cur_splice_state;
            end           
            SPLICE_START : begin
                nxt_splice_state = SPLICE_DASH;
            end
            SPLICE_DASH : begin
                if((splice_area_bad)||
                  ((cur_push_l_state == PUSH_L_ERR)&&fiber_r_fast_obj_found)||
                  ((cur_push_r_state == PUSH_R_ERR)&&fiber_l_fast_obj_found)||
                  ((cur_push_r_state == PUSH_R_ERR)&&(cur_push_l_state == PUSH_L_ERR))) begin
                    nxt_splice_state = SPLICE_ERR;
                end
                else if((cur_push_l_state == PUSH_L_WAIT)&&
                        (cur_push_r_state == PUSH_R_WAIT)) begin 
                    nxt_splice_state = SPLICE_CLEAN;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end                 
            end
            SPLICE_CLEAN : begin
                if(fiber_clean_ok) begin
                    nxt_splice_state = SPLICE_ADJUST;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end
            end
            SPLICE_ADJUST : begin
                if(fiber_align_ok)begin
                    nxt_splice_state = SPLICE_CLOSE;
                end 
                else begin
                    nxt_splice_state = cur_splice_state;
                end               
            end
            SPLICE_CLOSE: begin
                if((cur_push_l_state == PUSH_L_ERR)||
                   (cur_push_r_state == PUSH_R_ERR)) begin
                    nxt_splice_state = SPLICE_ERR;
                end
                else if((cur_push_l_state == PUSH_L_OK)&&
                        (cur_push_r_state == PUSH_R_OK)) begin 
                   nxt_splice_state = SPLICE_PAUSE1;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end
            end
            SPLICE_PAUSE1: begin
                if(pausemode1) begin
                    nxt_splice_state = (key_continue)?(SPLICE_ALIGN):(cur_splice_state);
                end
                else begin
                    nxt_splice_state = SPLICE_ALIGN;
                end   
            end   
            SPLICE_ALIGN : begin
                if(fiber_align_ok) begin
                    nxt_splice_state = SPLICE_PAUSE2;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end
            end 
            SPLICE_PAUSE2 : begin
                if(pausemode2) begin
                    nxt_splice_state = (key_continue)?(SPLICE_PREACT):(cur_splice_state);
                end
                else begin
                    nxt_splice_state = SPLICE_PREACT;
                end          
            end 
            SPLICE_PREACT: begin
                if(pre_splice_ok) begin
                    nxt_splice_state = SPLICE_PROC;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end
            end
            SPLICE_PROC: begin
                if(splice_proc_ok) begin
                    nxt_splice_state = SPLICE_REPORT;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end                
            end
            SPLICE_REPORT: begin
                if((~caliberation)&tention_mod&tention_rdy) begin
                    nxt_splice_state = SPLICE_TENTION;
                end
                else begin
                    nxt_splice_state = cur_splice_state;
                end                   
            end
            SPLICE_TENTION:begin
                nxt_splice_state = cur_splice_state;                   
            end  
            SPLICE_ERR : begin
                nxt_splice_state = cur_splice_state;                   
            end   
            SPLICE_INIT : begin
                nxt_splice_state = SPLICE_AREA_ERR;                   
            end   
            SPLICE_AREA_ERR : begin
                nxt_splice_state = cur_splice_state;                   
            end               
            default: begin
                nxt_splice_state = SPLICE_RESET;
            end       
        endcase
    end
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fusion_push_state <= 32'b0;        
        fusion_proc_state <= 32'b0;     
    end 
    else begin 
        fusion_push_state <= {cur_push_r_state,cur_push_l_state};    
        fusion_proc_state <= cur_splice_state;  
    end 
end 
//--------------------------------------------------------
reg[4:0] touch_status_ff1;
reg[4:0] touch_status_ff2;
//--------------------------------------------------------
reg[31:0] intr_gap_cntr;
localparam INTR_GAP = 1000000;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        intr_gap_cntr <= 32'hffffffff;           
    end 
	else if((fusion_proc_state == cur_splice_state)&&(touch_status_ff2 == touch_status_ff1)) begin 	
		intr_gap_cntr <= (intr_gap_cntr < INTR_GAP)?(intr_gap_cntr + 32'b1):intr_gap_cntr; 
	end
	else begin
	    intr_gap_cntr <= 32'b0 ;    
	end    
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fusion_proc_intr  <= 1'b0 ;
    end 
    else if(intr_gap_cntr < INTR_GAP) begin		
		fusion_proc_intr  <= 1'b1;		
    end
    else begin
    	fusion_proc_intr  <= 1'b0 ;
    end
end
//--------------------------------------------------------
parameter SENSER_PERIOD = 50_000_000;
//--------------------------------------------------------
reg[31:0] hall_sens_cntr;
reg       hall_touch_ff;
//--------------------------------------------------------
always @(posedge clk) hall_touch_ff <= hall_touch;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
    	hall_sens_cntr <= SENSER_PERIOD;
    end
    else if(~hall_touch_ff) begin
    	hall_sens_cntr <= (hall_sens_cntr < SENSER_PERIOD)?(hall_sens_cntr + 1):hall_sens_cntr; 
    end
    else begin
        hall_sens_cntr <= 0;
    end
end
//--------------------------------------------------------    
reg hall_sense;
reg hall_sense_ff1;
always @(posedge clk ) hall_sense      <= (hall_sens_cntr == SENSER_PERIOD)?1'b1:1'b0;
//--------------------------------------------------------    
always @(posedge clk ) fusion_touch_ff1<= fusion_touch;
always @(posedge clk ) init_touch_ff1  <= init_touch;
always @(posedge clk ) key_continue    <= fusion_touch&(~fusion_touch_ff1);
always @(posedge clk ) key_init        <= init_touch&(~init_touch_ff1);
always @(posedge clk ) hall_sense_ff1  <= hall_sense;
always @(posedge clk ) posr_touch_ff1  <= posr_touch;
always @(posedge clk ) posl_touch_ff1  <= posl_touch;
always @(posedge clk ) shell_close     <= hall_sense&(~hall_sense_ff1);
always @(posedge clk ) shell_open      <= (~hall_sense)&hall_sense_ff1;
always @(posedge clk ) posr_ready      <= posr_touch_ff1&(~posr_touch);
always @(posedge clk ) posl_ready      <= posl_touch_ff1&(~posl_touch);
//-------------------------------------------------------------
always @(posedge clk ) fiber_r_fast_obj_found  <= fast_r_edge_found;
always @(posedge clk ) fiber_l_fast_obj_found  <= fast_l_edge_found;
always @(posedge clk ) fiber_r_slow_obj_found  <= slow_r_edge_found;
always @(posedge clk ) fiber_l_slow_obj_found  <= slow_l_edge_found;
always @(posedge clk ) fiber_r_creep_obj_found <= creep_r_edge_touch;
always @(posedge clk ) fiber_l_creep_obj_found <= creep_l_edge_touch;
//-------------------------------------------------------------
reg[31:0] aux_ctrl_ff1;
always @(posedge clk ) aux_ctrl_ff1    <= fiber_aux_ctrl[31:0];
//--------------------------------------------------------
always @(posedge clk ) fiber_align_ok  <= (fiber_aux_ctrl[0])&(~aux_ctrl_ff1[0]);
always @(posedge clk ) fiber_no_err    <= (fiber_aux_ctrl[2])&(~aux_ctrl_ff1[2]);
always @(posedge clk ) fusion_start    <= (fiber_aux_ctrl[3])&(~aux_ctrl_ff1[3]);
always @(posedge clk ) fusion_init     <= (fiber_aux_ctrl[4])&(~aux_ctrl_ff1[4]);  
//--------------------------------------------------------
always @(posedge clk ) caliberation    <= fusion_push_ctrl[0];
always @(posedge clk ) pausemode1      <= fusion_push_ctrl[1];
always @(posedge clk ) pausemode2      <= fusion_push_ctrl[2];
always @(posedge clk ) engineer_mode   <= fusion_push_ctrl[7];
always @(posedge clk ) auto_splice     <= fusion_push_ctrl[8];
always @(posedge clk ) views_sel       <= fusion_push_ctrl[9];
always @(posedge clk ) push_en         <= fusion_push_ctrl[10];
always @(posedge clk ) tention_mod     <= fusion_push_ctrl[11];
always @(posedge clk ) slow_speed      <= fusion_push_ctrl[15:12] + 4;
always @(posedge clk ) last_push       <= fusion_push_ctrl[23:16] + 1;
always @(posedge clk ) last_speed      <= fusion_push_ctrl[27:24] + 1;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_l_base_ready <= 1'b0;    
    end 
    else if(cur_push_l_state == PUSH_L_INIT)begin 
        fiber_l_base_ready <= 1'b0;    
    end
    else if(force_pause_l&&(cur_push_l_state == PUSH_L_BASE))begin 
        fiber_l_base_ready <= 1'b1;    
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_r_base_ready <= 1'b0;    
    end 
    else if(cur_push_r_state == PUSH_R_INIT)begin 
        fiber_r_base_ready <= 1'b0;    
    end
    else if(force_pause_r&&(cur_push_r_state == PUSH_R_BASE))begin 
        fiber_r_base_ready <= 1'b1;    
    end 
end 
//--------------------------------------------------------
always @(posedge clk) keep_idle  <= engineer_mode|(~push_en)|(~fiber_r_base_ready)|(~fiber_l_base_ready);    
always @(posedge clk) splice_act <= shell_flag|key_continue|fusion_start;    
//-------------------------------------------------------------
always @(posedge clk ) touch_status_ff1 <= touch_status[4:0];
always @(posedge clk ) touch_status_ff2 <= touch_status_ff1;
always @(posedge clk ) {fusion_touch,hall_touch,posr_touch,posl_touch,init_touch} <= touch_status_ff1; 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fast_l_edge_touch <= 1'b0;
        fast_m_edge_touch <= 1'b0;
        fast_n_edge_touch <= 1'b0;
        slow_l_edge_touch <= 1'b0;
        slow_m_edge_touch <= 1'b0;
        slow_n_edge_touch <= 1'b0;
        fast_r_edge_touch <= 1'b0;
        fast_s_edge_touch <= 1'b0;
        fast_t_edge_touch <= 1'b0;
        slow_r_edge_touch <= 1'b0;
        slow_s_edge_touch <= 1'b0;
        slow_t_edge_touch <= 1'b0;
        creep_l_edge_touch<= 1'b0;
        creep_r_edge_touch<= 1'b0;
    end 
    else if(move_porc_last) begin 
        fast_l_edge_touch <= 1'b0;
        fast_m_edge_touch <= 1'b0;
        fast_n_edge_touch <= 1'b0;
        slow_l_edge_touch <= 1'b0;
        slow_m_edge_touch <= 1'b0;
        slow_n_edge_touch <= 1'b0;
        fast_r_edge_touch <= 1'b0;
        fast_s_edge_touch <= 1'b0;
        fast_t_edge_touch <= 1'b0;
        slow_r_edge_touch <= 1'b0;
        slow_s_edge_touch <= 1'b0;
        slow_t_edge_touch <= 1'b0; 
        creep_l_edge_touch<= 1'b0;
        creep_r_edge_touch<= 1'b0;        
    end
    else if(move_porc_v) begin 
        if(move_porc_data[27:16] == fusion_fast_l_b) fast_l_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_fast_m_b) fast_m_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_fast_n_b) fast_n_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_l_b) slow_l_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_m_b) slow_m_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_n_b) slow_n_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_fast_r_b) fast_r_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_fast_s_b) fast_s_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_fast_t_b) fast_t_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_r_b) slow_r_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_s_b) slow_s_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_slow_t_b) slow_t_edge_touch <= 1'b1;
        if(move_porc_data[27:16] == fusion_creep_l_b)creep_l_edge_touch<= 1'b1;
        if(move_porc_data[27:16] == fusion_creep_r_b)creep_r_edge_touch<= 1'b1;           
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fast_l_edge_found <= 1'b0;
        slow_l_edge_found <= 1'b0;
        fast_r_edge_found <= 1'b0;
        slow_r_edge_found <= 1'b0;
    end 
    else if(move_porc_last) begin 
        fast_l_edge_found <= fast_l_edge_touch&fast_m_edge_touch&fast_n_edge_touch;
        slow_l_edge_found <= slow_l_edge_touch&slow_m_edge_touch&slow_n_edge_touch;
        fast_r_edge_found <= fast_r_edge_touch&fast_s_edge_touch&fast_t_edge_touch;
        slow_r_edge_found <= slow_r_edge_touch&slow_s_edge_touch&slow_t_edge_touch;        
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        shell_flag <= 1'b0; 
    end 
    else if(auto_splice&shell_close)begin
        shell_flag <= 1'b1; 
    end    
    else if(fusion_init|shell_open) begin
        shell_flag <= 1'b0; 
    end    
end 
//--------------------------------------------------------
wire[12:0] fusion_gold_line_b = fusion_slow_l_x + fusion_slow_r_x;
wire[11:0] fusion_gold_line   = fusion_gold_line_b[12:1];
//--------------------------------------------------------
reg splice_area_touch;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        splice_area_touch <= 1'b0;    
    end 
    else if(move_porc_last) begin
        splice_area_touch <= 1'b0;
    end
    else if(move_porc_v&&(move_porc_data[27:16] == fusion_gold_line)) begin
        splice_area_touch <= 1'b1;
    end 
end 
//--------------------------------------------------------
reg splice_area_obj_found;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        splice_area_obj_found <= 1'b0;
    end 
    else if(move_porc_last) begin
        splice_area_obj_found <= splice_area_touch;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        splice_area_bad <= 1'b0;        
    end 
    else if(cur_splice_state == SPLICE_RESET)begin 
        splice_area_bad <= 1'b0;        
    end 
    else if((cur_splice_state == SPLICE_START)  
          ||(cur_splice_state == SPLICE_DASH)   
          ||(cur_splice_state == SPLICE_ADJUST) 
          ||(cur_splice_state == SPLICE_CLOSE)  
          ||(cur_splice_state == SPLICE_ALIGN)) begin
        splice_area_bad <= splice_area_obj_found;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_push_reset <= 1'b0;        
    end 
    else if((cur_push_l_state == PUSH_L_IDLE)||
            (cur_push_l_state == PUSH_L_INIT)||
            (cur_push_l_state == PUSH_L_BASE))begin 
        fiber_push_reset <= 1'b1;        
    end 
    else begin
        fiber_push_reset <= 1'b0;        
    end
end 
//--------------------------------------------------------
reg[31:0] tention_rdy_cntr;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        tention_rdy_cntr <= 32'b0;
        tention_rdy      <= 1'b0;       
    end 
    else if((cur_splice_state == SPLICE_PROC)&&(gaoya_ctrl_time == 0)) begin
        tention_rdy_cntr <= TENTION_DELAY_TIME;
        tention_rdy      <= 1'b0;         
    end
    else begin 
        tention_rdy_cntr <= (tention_rdy_cntr > 0)?(tention_rdy_cntr - 32'b1):tention_rdy_cntr; 
        tention_rdy      <= (tention_rdy_cntr ==  32'h0)?1'b1:1'b0;    
    end 
end 
//--------------------------------------------------------
reg[31:0] push_video_rdy_cntr;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        push_video_rdy_cntr <= 32'b0;
        push_video_rdy      <= 1'b0;       
    end 
    else if(cur_splice_state == SPLICE_START) begin
        push_video_rdy_cntr <= VIDEO_DELAY_TIME;
        push_video_rdy      <= 1'b0;         
    end
    else begin 
        push_video_rdy_cntr <= (push_video_rdy_cntr > 0)?(push_video_rdy_cntr - 32'b1):push_video_rdy_cntr; 
        push_video_rdy      <= (push_video_rdy_cntr ==  32'h0)?1'b1:1'b0;    
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_clean_ok <= 1'b0;        
    end 
    else if((cur_splice_state == SPLICE_DASH)&&(nxt_splice_state == SPLICE_CLEAN))begin
        fiber_clean_ok <= 1'b0;        
    end
    else if((cur_splice_state == SPLICE_CLEAN)&&(gaoya_ctrl_time == 0)) begin 
        fiber_clean_ok <= 1'b1;        
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        pre_splice_ok <= 1'b0;        
    end 
    else if((cur_splice_state == SPLICE_PAUSE2)&&(nxt_splice_state == SPLICE_PREACT))begin
        pre_splice_ok <= 1'b0;        
    end
    else if((cur_splice_state == SPLICE_PREACT)&&(gaoya_ctrl_time == 0)) begin 
        pre_splice_ok <= 1'b1;        
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        splice_proc_ok <= 1'b0;        
    end 
    else if((cur_splice_state == SPLICE_PREACT)&&(nxt_splice_state == SPLICE_PROC))begin
        splice_proc_ok <= 1'b0;        
    end
    else if((cur_splice_state == SPLICE_PROC)&&(gaoya_ctrl_time == 0)) begin 
        splice_proc_ok <= 1'b1;        
    end 
end 
//--------------------------------------------------------
reg[7:0]  pre_splice_force;
reg[31:0] pre_splice_time;
reg[7:0]  splice_force;
reg[31:0] splice_time;
reg[7:0]  clean_force;
reg[31:0] clean_time;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        clean_force      <= 'b0;
        clean_time       <= 'b0;        
        pre_splice_force <= 'b0;
        pre_splice_time  <= 'b0;
        splice_force     <= 'b0;
        splice_time      <= 'b0;
    end
    else begin
        clean_force      <= fusion_force_cfg[31:24]       ;
        clean_time       <= fusion_time_cfg[31:24]*100000 ;
        pre_splice_force <= fusion_force_cfg[23:16]       ;
        pre_splice_time  <= fusion_time_cfg[23:16]*100000 ;
        splice_force     <= fusion_force_cfg[7:0]         ;
        splice_time      <= fusion_time_cfg[15:0]*100000  ;
    end
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gaoya_ctrl_time <= 32'b0;        
    end 
    else if((cur_splice_state == SPLICE_DASH)&&(nxt_splice_state == SPLICE_CLEAN)) begin 
        gaoya_ctrl_time <= clean_time; 
    end 
    else if((cur_splice_state == SPLICE_PAUSE2)&&(nxt_splice_state == SPLICE_PREACT))begin
        gaoya_ctrl_time <= pre_splice_time;
    end
    else if((cur_splice_state == SPLICE_PREACT)&&(nxt_splice_state == SPLICE_PROC))begin
        gaoya_ctrl_time <= splice_time;
    end    
    else if(gaoya_ctrl_time > 0)begin
        gaoya_ctrl_time <= gaoya_ctrl_time - 1;        
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gaoya_ctrl_force <= 8'b0;        
    end 
    else if((cur_splice_state == SPLICE_DASH)&&(nxt_splice_state == SPLICE_CLEAN)) begin 
        gaoya_ctrl_force <= clean_force;
    end 
    else if((cur_splice_state == SPLICE_PAUSE2)&&(nxt_splice_state == SPLICE_PREACT))begin
        gaoya_ctrl_force <= pre_splice_force;
    end
    else if((cur_splice_state == SPLICE_PREACT)&&(nxt_splice_state == SPLICE_PROC))begin
        gaoya_ctrl_force <= splice_force;
    end        
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_l_base_err <= 1'b0;   
    end 
    else if(shell_open||key_init||fusion_init) begin
        fiber_l_base_err <= 1'b0;   
    end
    else if((cur_push_l_state == PUSH_L_READY)&&fiber_l_slow_obj_found) begin 
        fiber_l_base_err <= 1'b1;   
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_r_base_err <= 1'b0;   
    end 
    else if(shell_open||key_init||fusion_init) begin
        fiber_r_base_err <= 1'b0;   
    end
    else if((cur_push_r_state == PUSH_R_READY)&&fiber_r_slow_obj_found) begin 
        fiber_r_base_err <= 1'b1;   
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_l_missed_err <= 1'b0;        
    end 
    else if(fiber_push_reset)begin
        fiber_l_missed_err <= 1'b0;        
    end
    else if((cur_push_l_state == PUSH_L_FAST)&&(~posl_touch)) begin 
        fiber_l_missed_err <= 1'b1;        
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        fiber_r_missed_err <= 1'b0;        
    end 
    else if(fiber_push_reset)begin
        fiber_r_missed_err <= 1'b0;        
    end
    else if((cur_push_r_state == PUSH_R_FAST)&&(~posr_touch)) begin 
        fiber_r_missed_err <= 1'b1;        
    end 
end
//--------------------------------------------------------
assign fiber_push_status = {{4'b0,fiber_r_creep_obj_found,fiber_r_slow_obj_found,fiber_r_fast_obj_found,fiber_r_base_ready},
                            {4'b0,fiber_l_creep_obj_found,fiber_l_slow_obj_found,fiber_l_fast_obj_found,fiber_l_base_ready},
                            {5'h0,splice_area_bad,shell_flag,tention_rdy}, 
                            {2'b0,fiber_r_base_err,fiber_r_missed_err},
                            {2'b0,fiber_l_base_err,fiber_l_missed_err}};
//--------------------------------------------------------
localparam INIT_STEP  = 16'h100;
wire[5:0]  fast_speed = 8'd1;
wire[5:0]  tent_speed = 8'd4;
wire[5:0]  creep_speed= slow_speed + 8'd8;
wire       dpad       = 1'b0;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        motor_move_l <= 32'b0;  
    end 	
	else if(cur_push_l_state == PUSH_L_INIT) begin
        motor_move_l <= {dpad,~direct_front,pause_false,stop_false,fast_speed,6'h0,16'hffff};  
	end	
	else if(cur_push_l_state == PUSH_L_BASE) begin
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,fast_speed,6'h0,INIT_STEP[15:0]};  
	end
    else if(cur_push_l_state == PUSH_L_FAST) begin  //dash move
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,slow_speed,fast_speed,16'hffff};  // speed up
    end     
    else if(cur_push_l_state == PUSH_L_SLOW) begin //slowly move
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,slow_speed,6'h0,16'hffff}; // slow move 
    end
    else if(cur_push_l_state == PUSH_L_CREEP) begin //creep move
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,creep_speed,6'h0,16'hffff};  
    end    
    else if((cur_splice_state == SPLICE_ERR)&&fiber_l_missed_err) begin  //fast move
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,fast_speed,6'h0,{INIT_STEP[14:0],1'b0}};
    end     
    else if((~caliberation)&&(cur_splice_state == SPLICE_PROC)) begin
        motor_move_l <= {dpad,direct_front,pause_false,stop_false,last_speed,6'h0,{8'b0,last_push}};  
    end
	else if(cur_splice_state == SPLICE_TENTION) begin
        motor_move_l <= {dpad,~direct_front,pause_false,stop_false,tent_speed,6'h0,INIT_STEP[15:0]};  
    end   
    else if((cur_splice_state == SPLICE_REPORT)||(cur_splice_state == SPLICE_ERR)||(cur_push_l_state == PUSH_L_IDLE)) begin
        motor_move_l <= {dpad,direct_front,pause_false,stop_true,6'd0,6'h0,16'hffff};  
    end
    else begin
        motor_move_l <= {dpad,direct_front,pause_true,stop_false,6'd0,6'h0,16'hffff};  
    end
end   
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        motor_move_r <= 32'b0;  
    end 
	else if(cur_push_r_state == PUSH_R_INIT) begin
        motor_move_r <= {dpad,~direct_front,pause_false,stop_false,fast_speed,6'h0,16'hffff};  // target speed used!!!
	end	
	else if(cur_push_r_state == PUSH_R_BASE) begin
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,fast_speed,6'h0,INIT_STEP[15:0]};  
	end
    else if(cur_push_r_state == PUSH_R_FAST) begin  //dash move
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,slow_speed,fast_speed,16'hffff}; // speed up
    end 
    else if(cur_push_r_state == PUSH_R_SLOW) begin //slowly move
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,slow_speed,6'h0,16'hffff}; // slow move 
    end
    else if(cur_push_r_state == PUSH_R_CREEP) begin //creep move
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,creep_speed,6'h0,16'hffff};  
    end    
    else if((cur_splice_state == SPLICE_ERR)&&fiber_r_missed_err) begin  //fast move
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,fast_speed,6'h0,{INIT_STEP[14:0],1'b0}};
    end       
    else if((~caliberation)&&(cur_splice_state == SPLICE_PROC)) begin
        motor_move_r <= {dpad,direct_front,pause_false,stop_false,last_speed,6'h0,{8'b0,last_push}};  
    end 
	else if(cur_splice_state == SPLICE_TENTION) begin
        motor_move_r <= {dpad,~direct_front,pause_false,stop_false,tent_speed,6'h0,INIT_STEP[15:0]};  
    end    
    else if((cur_splice_state == SPLICE_REPORT)||(cur_splice_state == SPLICE_ERR)||(cur_push_r_state == PUSH_R_IDLE)) begin
        motor_move_r <= {dpad,direct_front,pause_false,stop_true,6'd0,6'h0,16'hffff};  
    end
    else begin
        motor_move_r <= {dpad,direct_front,pause_true,stop_false,6'd0,6'h0,16'hffff};  
    end
end   

endmodule
